package com.note.app.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.note.common.domain.Note;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * 笔记Mapper
 */
@Mapper
public interface NoteMapper extends BaseMapper<Note> {

    /**
     * 分页查询用户笔记列表
     * 
     * @param page 分页参数
     * @param userId 用户ID
     * @param collectionId 集合ID
     * @return 分页结果
     */
    @Select("<script>" +
    "SELECT n.* FROM note n " +
    "WHERE n.user_id = #{userId} AND n.deleted = 0 " +
    "<if test='collectionId != null'> AND n.collection_id = #{collectionId} </if>" +
    "<if test='collectionId == null'> AND (n.collection_id IS NULL OR n.collection_id = 0) </if>" +
    "ORDER BY n.updated_at DESC" +
    "</script>")
IPage<Note> selectPageByUserId(Page<Note> page, 
                        @Param("userId") Long userId, 
                        @Param("collectionId") Long collectionId);
    
    /**
     * 分页查询公开笔记列表
     * 
     * @param page 分页参数
     * @return 分页结果
     */
    @Select("SELECT n.* FROM note n " +
            "WHERE n.is_public = 1 AND n.deleted = 0 " +
            "ORDER BY n.updated_at DESC")
    IPage<Note> selectPublicNotePage(Page<Note> page);
    
    /**
     * 查询用户创建的笔记数量
     * 
     * @param userId 用户ID
     * @return 笔记数量
     */
    @Select("SELECT COUNT(*) FROM note WHERE user_id = #{userId} AND deleted = 0")
    int countNotesByUserId(@Param("userId") Long userId);
    
    /**
     * 查询集合下的笔记数量
     * 
     * @param collectionId 集合ID
     * @return 笔记数量
     */
    @Select("SELECT COUNT(*) FROM note WHERE collection_id = #{collectionId} AND deleted = 0")
    int countNotesByCollectionId(@Param("collectionId") Long collectionId);
    
    /**
     * 查询用户有权限访问的笔记
     * 包括：用户自己创建的笔记、公开的笔记
     * 
     * @param noteId 笔记ID
     * @param userId 用户ID
     * @return 笔记
     */
    @Select("SELECT n.* FROM note n " +
            "WHERE n.id = #{noteId} AND n.deleted = 0 " +
            "AND (n.user_id = #{userId} OR n.is_public = 1)")
    Note selectNoteWithPermission(@Param("noteId") Long noteId, @Param("userId") Long userId);

    /**
     * 查询用户的所有笔记
     *
     * @param userId 用户ID
     * @return 笔记列表
     */
    @Select("SELECT * FROM note WHERE user_id = #{userId} AND deleted = 0")
    List<Note> selectByUserId(@Param("userId") Long userId);

    /**
     * 通过标题搜索笔记（MySQL全文索引）
     *
     * @param userId 用户ID
     * @param includePublic 是否包含公开笔记
     * @param collectionId 集合ID，可为null
     * @param keyword 关键词
     * @param offset 偏移量
     * @param size 数量
     * @return 笔记列表
     */
    @Select({"<script>",
            "SELECT * FROM note WHERE deleted = 0 ",
            "AND (user_id = #{userId} ",
            "<if test='includePublic'>OR is_public = 1</if>) ",
            "<if test='collectionId != null'>AND collection_id = #{collectionId}</if> ",
            "AND title LIKE CONCAT('%', #{keyword}, '%') ",
            "ORDER BY updated_at DESC ",
            "LIMIT #{offset}, #{size}",
            "</script>"})
    List<Note> searchNotesByTitle(@Param("userId") Long userId, 
                                 @Param("includePublic") Boolean includePublic,
                                 @Param("collectionId") Long collectionId,
                                 @Param("keyword") String keyword,
                                 @Param("offset") Integer offset,
                                 @Param("size") Integer size);

    /**
     * 通过内容ID列表查询笔记
     *
     * @param userId 用户ID
     * @param includePublic 是否包含公开笔记
     * @param contentIds 内容ID列表
     * @return 笔记列表
     */
    @Select({"<script>",
            "SELECT * FROM note WHERE deleted = 0 ",
            "AND (user_id = #{userId} ",
            "<if test='includePublic'>OR is_public = 1</if>) ",
            "AND content_id IN ",
            "<foreach collection='contentIds' item='id' open='(' separator=',' close=')'>",
            "#{id}",
            "</foreach>",
            "</script>"})
    List<Note> selectByContentIds(@Param("userId") Long userId, 
                                 @Param("includePublic") Boolean includePublic,
                                 @Param("contentIds") List<String> contentIds);
} 